package com.clay.appointment.service.Impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.clay.appointment.entity.dict.Dict;
import com.clay.appointment.listener.DictListener;
import com.clay.appointment.mapper.DictMapper;
import com.clay.appointment.service.DictService;
import com.clay.appointment.vo.dict.DictExcelVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author : clay
 * @Description:
 * @Date: Create in 21:47 2021/7/25
 * @Modified By:
 */
@Service
@Slf4j
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {

    @Resource
    private DictMapper dictMapper;
    @Resource(name = "redisTemplate")
    private RedisTemplate<Object, Object> redisTemplate;

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * @param id 查询的数据的id
     * @return 根据数据id查询返回的子数据列表
     */
    @Override
    @Cacheable(value = "dict", keyGenerator = "myKeyGenerator")
    public List<Dict> findChildrenData(Long id) {
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", id);
        List<Dict> dictList = dictMapper.selectList(wrapper);
        for (Dict dict : dictList) {
            if (hasChildren(dict.getId())) {
                dict.setHasChildren(true);
            }
        }
        return dictList;
    }

    @Override
    public void exportDictData(HttpServletResponse response) {
        try (OutputStream outputStream = response.getOutputStream()) {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyExcel没有关系
            String fileName = URLEncoder.encode("数据字典", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            //查询数据库
            List<Dict> dictList = dictMapper.selectList(null);
            List<DictExcelVO> dictExcelVOList = new ArrayList<>();

            for (Dict dict : dictList) {
                DictExcelVO dictExcelVO = new DictExcelVO();
                BeanUtils.copyProperties(dict, dictExcelVO);
                dictExcelVOList.add(dictExcelVO);
            }
            EasyExcel.write(outputStream, DictExcelVO.class).sheet("dict").doWrite(dictExcelVOList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    @CachePut(value = "dict")
    public void importDictData(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(), DictExcelVO.class, new DictListener(dictMapper)).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //redisson
        ValueOperations<Object, Object> ops = redisTemplate.opsForValue();
        ops.set("token", "token", 30, TimeUnit.MINUTES);
        if (ops.get("token") != null) {
            ops.set("token", "token", 30, TimeUnit.MINUTES);
        }
    }

    @Cacheable(value = "dict", keyGenerator = "myKeyGenerator")
    @Override
    public String getNameByParentDictCodeAndValue(String parentDictCode, String value) {
        //如果value能唯一定位数据字典，parentDictCode可以传空，例如：省市区的value值能够唯一确定
        if (StringUtils.isEmpty(parentDictCode)) {
            Dict dict = dictMapper.selectOne(new QueryWrapper<Dict>().eq("value", value));
            if (null != dict) {
                return dict.getName();
            }
        } else {
            Dict parentDict = this.getByDictCode(parentDictCode);
            if (null == parentDict) {
                return "";
            }
            Dict dict = dictMapper.selectOne(new QueryWrapper<Dict>().eq("parent_id", parentDict.getId()).eq("value", value));
            if (null != dict) {
                return dict.getName();
            }
        }
        return "";
    }

    @Override
    public List<Dict> findByDictCode(String dictCode) {
        Dict dict = this.getByDictCode(dictCode);
        if (null == dict) {
            return null;
        }
        return this.findChildrenData(dict.getId());
    }


//    @Override
//    @Async
//    public void findByDictCode1(String dictCode) {
//        threadPoolTaskExecutor.execute(() -> {
//            try {
//                TimeUnit.SECONDS.sleep(5);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("1111");
//        });
//        try {
//            TimeUnit.SECONDS.sleep(10);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        //callable
//        Dict dict = this.getByDictCode(dictCode);
//
//        System.out.println(this.findChildrenData(dict.getId()));
//    }

    private Dict getByDictCode(String dictCode) {
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dict_code", dictCode);
        return dictMapper.selectOne(queryWrapper);
    }


    private boolean hasChildren(Long id) {
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", id);
        Integer count = dictMapper.selectCount(wrapper);
        return count > 0;
    }

//    @Override
//    @Scheduled(cron = "0/5 * * * * ?")
//    public void testSchedule() {
//        //定期执行 线程等级最低
//        //1.同步数据 数据库-》缓存
//        //2.统计数据 一定时间范围
//        //3.错峰执行 任务占用资源太多
//        System.out.println("test");
//        int a = 1;
//        a = a;
//        a = a + 1;
//        System.out.println(a++);//1
//        System.out.println(++a);//3
//        //juc java并发包 所有常用集合都有安全代替类
//        //线程池五大参数
//        //BigDecimal 计算精度问题
//        BigDecimal decimal = new BigDecimal("1.0");
//        List<String> list = new ArrayList<>();
//        for (String s : list) {
//
//        }
//
//        //Iterator
//        for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
//            iterator.next();
//            iterator.remove();
//        }
        //LinkedList  ArrayList(索引下标，地址偏移量）扩容 100w
//        Stream<Object> objectStream = list.parallelStream().map();
//        ConcurrentHashMap
//    }
}
